/**
 * Copyright (c) 2010 BullionXpress.com,
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
package com.bullionxpress.server.impl;

import com.bullionxpress.shared.model.Account;
import com.bullionxpress.shared.service.AccountNotFoundException;
import java.rmi.RemoteException;
import com.bullionxpress.shared.service.DuplicateInstrumentIDException;
import com.bullionxpress.shared.service.InstrumentNotFoundException;
import com.bullionxpress.shared.service.InvalidInstrumentIDFormatException;
import com.bullionxpress.shared.service.InstrumentDatabase;
import com.bullionxpress.shared.model.Instrument;
import com.bullionxpress.shared.model.Transaction;
import com.bullionxpress.shared.model.TransactionType;
import com.bullionxpress.shared.service.AdminService;
import com.bullionxpress.shared.service.InsufficientFundingException;
import com.bullionxpress.shared.service.InvalidAmountException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import com.bullionxpress.shared.util.Log;
import java.sql.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AdminManager extends java.rmi.server.UnicastRemoteObject implements AdminService {

    public AdminManager() throws RemoteException {
        //What should go in the constructor?
        connect();
    }
    Connection conn = null;
    Statement statement = null;

    public void connect() {

        try {
            conn = DatabaseManager.getConnection();

        } catch (Exception ex) {
            Log.info(ex);
            ex.printStackTrace();
        }
    }

    public void deposit(String accountId, double amount) throws AccountNotFoundException, InvalidAmountException, RemoteException {
        //throw new UnsupportedOperationException("Not supported yet.");
        AccountRegistrar reg = new AccountRegistrar();
        Account a = reg.get(accountId);
        if (amount <= 0) {
            throw new InvalidAmountException("You cannot deposit a negative amount");
        }
        try {
            statement = conn.createStatement();
            statement.executeUpdate("UPDATE accounts SET balance = balance + " + amount + ", initial = initial + " + amount + " WHERE id = '" + accountId + "'");
            TransactionManager tm = new TransactionManager();
            Transaction t = new Transaction();
            t.setInstrument(new Instrument("-"));
            t.setType(TransactionType.DEPOSIT);
            t.setPrice(amount);
            t.setSellerId("-");// should it be robot?
            t.setBuyerId(accountId);
            t.setDate(new Date(System.currentTimeMillis()));
            t.setTimestamp(System.currentTimeMillis());
            t.setUnits(0);
            tm.add(t);

        } catch (Exception ex) {
            Log.info(ex);
        }
    }

    public void withdrawal(String accountId, double amount) throws AccountNotFoundException, InsufficientFundingException, InvalidAmountException, RemoteException {
        //throw new UnsupportedOperationException("Not supported yet.");
        AccountRegistrar reg = new AccountRegistrar();
        Account a = reg.get(accountId);

        if (a.getBalance() - amount < 0) {
            throw new InsufficientFundingException("You cause account to go into a debit position");
        }
        if (amount <= 0) {
            throw new InvalidAmountException("You cannot deposit a negative amount");
        }
        try {
            statement = conn.createStatement();
            statement.executeUpdate("UPDATE accounts SET balance = balance - " + amount + ", initial = initial - " + amount + " WHERE id = '" + accountId + "'");
            TransactionManager tm = new TransactionManager();
            Transaction t = new Transaction();
            t.setInstrument(new Instrument("-"));
            t.setPrice(-amount);
            t.setType(TransactionType.WITHDRAWAL);
            t.setSellerId("-");// should it be robot?
            t.setBuyerId(accountId);
            t.setTimestamp(System.currentTimeMillis());
            t.setDate(new Date(System.currentTimeMillis()));
            t.setUnits(0);
            tm.add(t);
        } catch (Exception ex) {
            Log.info(ex);
        }



    }

    public int getCondolidatedUnits(Instrument instrument) throws InstrumentNotFoundException, RemoteException {
        int result = 0;
        try {
            statement = conn.createStatement();
            ResultSet r = statement.executeQuery("select sum(units) from positions where accountid != 'A7827383' and symbol = '" + instrument.getSymbol() + "'");
            if (r.next()) {
                result = r.getInt(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(AdminManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }

    public double getCondolidatedBalance() throws RemoteException {
        double result = 0;
        try {
            statement = conn.createStatement();
            ResultSet r = statement.executeQuery("select sum(balance) from accounts where owner != 'robot'");
            if (r.next()) {
                result = r.getDouble(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(AdminManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }

    public int getNumberOfAccounts() throws RemoteException {
        int result = 0;
        try {
            statement = conn.createStatement();
            ResultSet r = statement.executeQuery("select count(distinct(id)) from accounts where owner != 'robot'");
            if (r.next()) {
                result = r.getInt(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(AdminManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }

    public int getNumberOfTransactions() throws RemoteException {
        int result = 0;
        try {
            statement = conn.createStatement();
            ResultSet r = statement.executeQuery("select count(*) from transactions");
            if (r.next()) {
                result = r.getInt(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(AdminManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }
}
